/*
 * Platzad
 * Copyright 2008 Shayne Riley
 *
 * This file is part of Platzad.
 *
 * Platzad is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Platzad is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Platzad.  If not, see <http://www.gnu.org/licenses/>.
 *
 * To contact the authors on questions or issues regarding the license,
 * you may send an email to <shayner at gmail dot com> or write to
 * Shayne Riley / P.O. Box 1092 / McCook, NE 69001.
 */

#include "Audio.h"
#include <SDL/SDL.h>
#include <iostream>
#include "SDLDelegate.h" // Helps with starting sdl-based systems.

namespace pzdAudio
{

Audio& Audio::getInstance()
{
	// Because it is static, the destructor is called automatically at the
	// end of the application or thread or something.
	static Audio instance;

	return instance;
}

Audio::Audio()
: mAudioGood(false), mPlayBGM(false), audio(NULL), music(NULL)
{
    init();
}

Audio::~Audio()
{
    finalize();
}

void Audio::finalize()
{
	using namespace std;

    cout << "Audio subsystem shut down." << endl;
}

void Audio::init()
{
	using namespace std;

	// Initialize SDL core if needed.
	if(!pzd::SDLDelegate::getInstance().needSDL())
	{
		// Failure
		cerr << "SDL not able to initialize, audio sub-system cannot "
			<< "initialize." << endl;
		return;
	}
    // Initializes the SDL Audio for use.
    if(SDL_Init(SDL_INIT_AUDIO) != 0)
    {
        cerr << "Error: " << SDL_GetError() << endl;
        return;
    }
    else
    {
        cout << "SDL Audio initialized." << endl;
    }

	// Initialize the mixer.
	if(Mix_OpenAudio(
			AUDIO_RATE, AUDIO_FORMAT, AUDIO_CHANNELS, AUDIO_BUFFER_SIZE) != 0)
	{
		cerr << "SDL_mixer not initialized. Error: " << Mix_GetError() << endl;
		return;
	}
	else
	{
		cout << "SDL_mixer initialized." << endl;
	}

	mAudioGood = true;

    // Because we are using SDL_mixer, we do not need to provide our own audio
    // thread. Or, at least, not yet.
}

bool Audio::loadBGM(std::string filename)
{
	using namespace std;
	cout << "Yo yo yo, I'm loading music from " << filename.c_str() << endl;
	/*
	 * Load the new music. If it fails, then nothing happens to the currently
	 * playing music. If it succeeds, then the current music is replaced by
	 * the loaded music. If the current music was playing, then the new music
	 * will start playing as well. Yeah, I know this function is called
	 * "loadBGM" and that resuming music lies outside the scope, but then again
	 * so does stopping the music, so you can simmer down now. (Heh. Game. Set.
	 * Match. The name: shayner)
	 */

	Mix_Music *newMusic = Mix_LoadMUS(filename.c_str());

	// If newMusic is null, it means the loading failed. D'Oh!
	if(newMusic == NULL)
	{
		// Just get out man. Nothing else needs to occur.
		cerr << "Unable to load music file: " << Mix_GetError() << endl;
		return false;
	}

	// Stop the current music and load the new music.
	bool wasPlaying = mPlayBGM;
	if(music != NULL)
	{
		Mix_HaltMusic();
		Mix_FreeMusic(music);
		music = NULL;
	}

	music = newMusic;

	if(Mix_PlayMusic(music, 0) == -1)
	{
		// Attemps to play the music failed. Notify and leave.
		cerr << "Unable to play music file: " << Mix_GetError() << endl;
		return false;
	}

	// If the music wasn't playing, it should pause until it needs to play.
	if(!wasPlaying)
	{
		pauseBGM();
	}

	return true;
}

void Audio::playBGM()
{
	if(music != NULL)
	{
		std::cout << "HELLO!!!!" << std::endl;
		mPlayBGM = true;
		Mix_ResumeMusic();
	}
}

void Audio::pauseBGM()
{
	if(music != NULL)
	{
		mPlayBGM = false;
		Mix_PauseMusic();
	}
}

bool Audio::loadAudio(std::string filename)
{
	using namespace std;
	cout << "Yo yo yo, I'm loading an audio clip from " << filename.c_str() << endl;

	// If audio was previously loaded, stop it, free it, and load the new goods.
	if(audio != NULL)
	{
		Mix_HaltChannel(0); // Currently audio is only on channel 0.
		Mix_FreeChunk(audio);
		audio = NULL;
	}

	audio = Mix_LoadWAV(filename.c_str());

	// If audio is null, it means the loading failed. D'Oh!
	if(audio == NULL)
	{
		// Just get out man. Nothing else needs to occur.
		cerr << "Unable to load audio file: " << Mix_GetError() << endl;
		return false;
	}

	return true;
}

void Audio::playAudio() {
	if(audio != NULL)
	{
		std::cout << "AUDIO!!!!" << std::endl;
		Mix_PlayChannel(0, audio, 0);
	}
}

} // namespace
